// ignore_for_file: file_names

import 'package:dio/dio.dart';
import 'package:flutter_house_manager/constans/index.dart';
import 'package:flutter_house_manager/utils/Emitter.dart';
import 'package:flutter_house_manager/utils/TokenManager.dart';

class Requestdio {
  final Dio _dio = Dio();
  // 主构造函数
  Requestdio() {
    // 正常写法:
    // 基础地址
    // _dio.options.baseUrl = GlobalVariable.BASE_URL;
    // 连接超时时间
    // _dio.options.connectTimeout = const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT);
    // 接收超时时间
    // _dio.options.receiveTimeout = const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT);

    // 链式写法:
    _dio.options
      ..baseUrl = GlobalVariable.BASE_URL
      ..connectTimeout = const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT)
      ..receiveTimeout = const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT);

    // 添加拦截器
    _dio.interceptors.add(
      InterceptorsWrapper(
        // 请求拦截器
        onRequest: (context, handler) {
          // 注入token
          String token = tokenManager.getToken();
          if (token.isNotEmpty) {
            context.headers["Authorization"] = 'Bearer $token';
          }
          handler.next(context); // 继续发送请求
        },
        // 响应拦截器
        onResponse: (context, handler) {
          // 处理响应错误
          if (context.statusCode! >= 200 && context.statusCode! <= 300) {
            // 响应成功
            handler.next(context);
          } else {
            // 响应失败
            handler.reject(DioException(requestOptions: context.requestOptions));
          }
        },
        // 错误拦截器
        onError: (context, handler) async {
          // 判断状态码为401
          if (context.response!.statusCode == 401) {
            // 1. 获取refreshToken
            String refreshToken = tokenManager.getRefreshToken();
            if (refreshToken.isNotEmpty) {
              // 1.1 调用接口刷新token
              try {
                await _refresh();
                // 1.2 能够到这里, 说明token已经刷新
                // 重新发起请求, 把之前的请求重新发一次(无感请求)
                return handler.resolve(await _dio.fetch(context.requestOptions));
              } on Exception catch (e) {
                eventBus.fire(LogoutEvent(e.toString()));
              }
            } else {
              eventBus.fire(LogoutEvent('401 未授权'));
            }
          }
          handler.reject(context);
        },
      ),
    );
  }

  /// 调用接口去刷新token
  _refresh() async {
    // 1. 获取refreshToken
    String refreshToken = tokenManager.getRefreshToken();
    // 2. 发起请求
    Dio newDio = Dio();
    final res = await newDio.post(
      '${GlobalVariable.BASE_URL}${HTTP_PATH.REFRESH_TOKEN}',
      options: Options(
        headers: {
          "Authorization": 'Bearer $refreshToken',
        },
      ),
    );
    // 3. 存储新的token
    tokenManager.setToken(res.data['data']['token'], refreshToken: res.data['data']['refreshToken']);
  }

  // 2. 定义方法
  get(String url, {Map<String, dynamic>? params}) {
    return _handleRes(_dio.get(url, queryParameters: params));
  }

  post(String url, {Map<String, dynamic>? data}) {
    return _handleRes(_dio.post(url, data: data));
  }

  put(String url, {Map<String, dynamic>? data}) {
    return _handleRes(_dio.put(url, data: data));
  }

  delete(String url, {Map<String, dynamic>? params, Map<String, dynamic>? data}) {
    return _handleRes(_dio.delete(url, queryParameters: params, data: data));
  }

  // 上传
  upload(String url, {FormData? data}) {
    return _handleRes(_dio.post(url, data: data));
  }

  // 3. 数据剥离
  _handleRes(Future<Response<dynamic>> task) async {
    final res = await task;
    // 请求成功
    if (res.data['code'] == GlobalVariable.SUCCESS_CODE) {
      return res.data['data'];
    }
    // 请求失败
    throw DioException(requestOptions: res.requestOptions);
  }
}

final Requestdio requestDio = Requestdio();
